
#include <stdint.h>
#include <string.h>

#include "Bsp_Delay.h"

#include "Debug.h"
/*Driver*/
#include "WCI.h"
#include "Timer.h"
/*Util*/
#include "Bit.h"
#include "Buffer.h"

#include "ID_i2c.h"
#include "ID_uart.h"
#include "ID_Process.h"

volatile uint8_t idFlags;
volatile uint32_t idTick;

volatile uint32_t sectionCount;

static Timer_T idTimer;
static uint8_t idI2cMem[275];
Buffer_T idI2cBuffer = {
	.buffer = idI2cMem,
};
static const uint8_t idNak[] = {0x00, 0x00, 0x24};
static uint8_t idCardRespBuf[275];

//	static SemaphoreHandle_t idCardSemaphore;

static void ID_Timer_Callback(void){
	idTick = 0;
}
void ID_Init(void){
//		idCardSemaphore = xSemaphoreCreateBinary();
	Timer_Setup(&idTimer, 50, 0, 0, ID_Timer_Callback);
	ID_Uart_Init();
	ID_I2C_Init();
}

static void ID_Notify(void){
#if 0
	static BaseType_t xHigherPriorityTaskWoken;
	xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR(idCardSemaphore, &xHigherPriorityTaskWoken);
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
#endif 
}

void ID_I2C_Notify(void){
	Bit_set(idFlags, 1);
	ID_Notify();
}

void ID_Uart_Notify(void){
	Bit_set(idFlags, 2);
	ID_Notify();
}

static int ID_I2C_DoProcess(void){
	int ret;
	unsigned rlen = 0;
	
	//Exchange with Card
//		ret = PcdComTransCPU(idI2cBuffer.buffer, idI2cBuffer.length, idCardRespBuf, &rlen, errorFlag);
	ret = WCI_Exchange(0, idI2cBuffer.buffer, idI2cBuffer.length, idCardRespBuf, &rlen, 275, WaitTime_Ms(60, 0), 0);
	
	if(!ret){
		sectionCount++;
//			if(idI2cBuffer.length == 3 && idI2cBuffer.buffer[0] == 0x05 && rlen < 13)
			idCardRespBuf[rlen++] = 0;
		ID_I2C_Send(idCardRespBuf, rlen);
	}
	else{
		ID_I2C_Send(idNak, sizeof(idNak));
	}
	return ret;
}


static int ID_SectionProcess(Buffer_T* cmd, Buffer_T* resp, uint32_t waitTime){
	int ret; 	
	
	idFlags = 0;
	sectionCount = 0;
	ID_Uart_SetupReceive(resp);
	ID_Uart_SendBuffer(cmd);
	idTick = waitTime / 10 + 1;
	Timer_Reset(&idTimer, idTick);
	while(1){		
		if(Bit_test(idFlags, 1)){
			Bit_clear(idFlags, 1);
			ID_I2C_DoProcess();
		}
		if(Bit_test(idFlags, 2)){
			ret = 0;
			break;
		}
		if(idTick == 0){
			ret = 1;
			break;
		}
	}
	
	return ret;
}


static uint32_t IDCard_CheckResponeStatus(Buffer_T* resp) {
    uint8_t SW1 = resp->buffer[7];
    uint8_t SW2 = resp->buffer[8];
    uint8_t SW3 = resp->buffer[9];

    return (SW1 == 0) && (SW2 == 0) && (SW3 == 0x90);
}

static int ID_CmdProcess(Buffer_T* cmd, Buffer_T* resp, uint32_t waitTime){
	int ret;
	
    resp->buffer[7] = 0xFF;
    resp->buffer[8] = 0xFF;
    resp->buffer[9] = 0xFF;
	ret = ID_SectionProcess(cmd, resp, waitTime);
	if(!ret){
		ret = IDCard_CheckResponeStatus(resp) ? 0 : 2;
	}
	return ret;
}

static int IDCard_Polling(Buffer_T* resp) {
    uint8_t cmd[] = {0xaa , 0xaa , 0xaa , 0x96 , 0x69 , 0x00 , 0x03 , 0x20, 0x01 , 0x22};
    Buffer_T cmdBuffer = {cmd, 0, sizeof(cmd)};
    int ret;
    
    memset(&resp->buffer[7], 0xFF, 3);
    ret = ID_SectionProcess(&cmdBuffer, resp, 500);
    if(ret){
		return ret;
    }
    if(memcmp(&resp->buffer[7], "\x00\x00\x9F", 3) != 0){
		return 2;
    }
    return 0;
}

static int IDCard_Select(Buffer_T* resp) {
    uint8_t cmd[] = {0xaa , 0xaa , 0xaa , 0x96 , 0x69 , 0x00 , 0x03 , 0x20 , 0x02 , 0x21};
    Buffer_T cmdBuffer = {cmd, 0, sizeof(cmd)};
    return ID_CmdProcess(&cmdBuffer, resp, 500);
}

static int IDCard_ReadInfo(Buffer_T* resp){
    uint8_t cmd[] = {0xaa , 0xaa , 0xaa , 0x96 , 0x69 , 0x00 , 0x03 , 0x30 , 0x01 , 0x32};
    Buffer_T cmdBuffer = {cmd, 0, sizeof(cmd)};
    return ID_CmdProcess(&cmdBuffer, resp, 1000);
}

static int IDCard_ReadInfoAndFinger(Buffer_T* resp){
    uint8_t cmd[] = {0xaa , 0xaa , 0xaa , 0x96 , 0x69 , 0x00 , 0x03 , 0x30 , 0x10 , 0x23};
    Buffer_T cmdBuffer = {cmd, 0, sizeof(cmd)};
    return ID_CmdProcess(&cmdBuffer, resp, 1000);
}

int ID_ReadInfo(Buffer_T * resp){
	int ret;
	ret = IDCard_Polling(resp);
	if(ret){
		return ret;
	}

	ret = IDCard_Select(resp);
	if(ret){
		return ret;
	}

	ret = IDCard_ReadInfo(resp);

	return ret;
}

static int ID_ReadInfoAndFinger(Buffer_T* resp){
	int ret;
	ret = IDCard_Polling(resp);
	if(ret){
		return ret;
	}

	ret = IDCard_Select(resp);
	if(ret){
		return ret;
	}

	ret = IDCard_ReadInfoAndFinger(resp);

	return ret;
}

int ID_Operation(uint8_t op, Buffer_T* resp){
	int ret = -1;
	
	switch(op){
	case 0: ret = ID_ReadInfo(resp); break;
	case 1: ret = ID_ReadInfoAndFinger(resp); break;
	}
	return ret;
}


int ID_CheckSAMVStatus(void){
    uint8_t cmd[] = {0xaa , 0xaa , 0xaa , 0x96 , 0x69 , 0x00 , 0x03 , 0x11, 0xFF , 0xED};
    Buffer_T cmdBuffer = {cmd, 0, sizeof(cmd)};
	uint8_t resp[16];
	Buffer_T respBuffer = {resp, 0, sizeof(resp)};
	return ID_CmdProcess(&cmdBuffer, &respBuffer, 500);
}

//	#include "Debug.h"

void ID_Test(void){
#if 1
	int ret;

	static uint8_t idTestBuf[2048];
	static Buffer_T idRespBuffer;
	idRespBuffer.buffer = idTestBuf;
	ID_Init();
	while(1){
		BSP_Delay_ms(10);
		WCI_SetRf(0, 1);
		BSP_Delay_ms(10);
		WCI_SetMode(0, WCI_Mode_B);
		idRespBuffer.length = 0;
		ret = ID_ReadInfo(&idRespBuffer);
		if(ret == 0){
			DBG_WRITE("ID Read OK\r\n");
		}
		WCI_SetRf(0, 0);
		BSP_Delay_ms(200);
	}
#endif 
}

int ID_Process(Buffer_T* cmd, Buffer_T* resp){
	return ID_CmdProcess(cmd, resp, 1000);
}

